/*
 * detectface.h
 *
 *  Created on: 2016年3月17日
 *      Author: guyadong
 */

#ifndef FACEDETECT_DETECTFACE_H_
#define FACEDETECT_DETECTFACE_H_
#include "detect_cl.h"
#include "casinfo.h"
#include "gray_matrix_cl.h"
#include "measure.h"
#include <memory>
namespace gdface {
object_info_vector create_return_vector_norm(const detected_objects_buffer_norm &object_buffer ,const cl_float2& normalization_factor);

object_info_vector create_return_vector(const detected_objects_buffer_norm &object_buffer, const cl_int2 &img_size);


struct feather_block:public feather_block_base {
	struct_vector_cl<feather_short_cl> feathers;
	feather_block() = default;
	feather_block(size_t start_layer, size_t end_layer, size_t offset, const struct_vector_cl<feather_short_cl>&feathers)
		:feather_block_base{ cl_int(start_layer),cl_int(end_layer),cl_int(offset) }, feathers(feathers){
	}
};
using scale_index_type = std::pair<int, int>;
using scale_size_type = std::vector<size_t>;

class detect_face {
	struct_cl<casinfo_base_float> cas_base;
	struct_vector_cl<feather_cl> feathers;
	struct_vector_cl<feather_short_cl> feathers_short;
	std::vector<std::vector<feather_block>> v_feathers_constant;
	const facecl_context& context;
	std::vector<feather_block> make_feathers_block(size_t max_block_size);
	using integral_matrixs_type=std::tuple<matrix_cl<cl_float,cl::Buffer>,matrix_cl<cl_float,cl::Buffer>>;
	/*
	 * 计算指定灰度图像矩阵的积分图和积方图
	 * tuple中第一个类型matrix_cl矩阵为积分图
	 * 第二个matrix_cl矩阵为积方图
	 */
	integral_matrixs_type create_integral(const gray_matrix_cl& img) const;

	using hit_mat_type=matrix_cl<cl_uchar,cl::Buffer>;
	using mean_mat_type=matrix_cl<cl_float,cl::Buffer>;
	using variance_mat_type=mean_mat_type;
	using out_mat_type=std::tuple<hit_mat_type,mean_mat_type,variance_mat_type>;

	out_mat_type create_out_matrixs(size_t integral_width, size_t integral_height, size_t detect_win_size) const;

	out_mat_type create_out_matrixs(size_t integral_width, size_t integral_height, size_t detect_win_size, size_t sample_step) const;

	hit_mat_type create_hit_full_matrix(size_t integral_width, size_t integral_height, size_t detect_win_size) const;

	using density_mat_type=matrix_cl<cl_ushort,cl::Buffer>;
	density_mat_type create_density_matrix(const hit_mat_type& hit_mat, size_t detect_win_size) const;
	void cobject_cluster(density_mat_type& dest_mat,struct_cl<detected_objects_buffer_norm>& detected_objects,const cl_int2 &img_size,const size_t detect_win_size)const;
	hit_mat_type haar_feather_filter(const detect_param& param, const integral_matrixs_type& integ_matrixs, struct_cl<detected_objects_buffer_norm>& detected_objects) const;

	void detect_on_integral(const detect_param& param, const integral_matrixs_type& integ_matrixs, struct_cl<detected_objects_buffer_norm>& object_buffer, gray_matrix_cl& zoom) const;
	std::shared_ptr<struct_cl<detected_objects_buffer_norm> > make_detected_objects_buffer_norm() const;
	std::shared_ptr<struct_cl<detected_objects_buffer_level> > make_detected_objects_buffer_level() const;

	/*
	 * 检测任务，
	 * 第一个float为图像缩小的比例，
	 * 第二个int为基于measure.detect_win_size的当前任务最大检测窗口尺寸的下标
	 * 第三个int为基于measure.detect_win_size的当前任务最小检测窗口尺寸的下标
	 * */
	using detect_task=std::pair<float,scale_index_type>;
	using detect_plan=std::vector<detect_task>;
	static detect_plan make_detect_plan(const size_t img_size, const detect_param& param);
	static detect_plan make_detect_plan(const gray_matrix_cl& img, const detect_param& param);
	static detect_plan make_detect_plan(const gf_int2& img_size, const detect_param& param);
public:
	detect_face(facecl_context& context = global_facecl_context);
	detect_face(const casinfo_cl& cas, facecl_context& context = global_facecl_context);
	detect_face& operator =(const detect_face& lv);
	detect_face& operator =(detect_face&& rv);
	object_info_vector detect(const gray_matrix_cl& img, const detect_param& param) const;
	virtual ~detect_face(){
	};
};


} /* namespace gdface */

#endif /* FACEDETECT_DETECTFACE_H_ */
